package com.xiashitech.apiservice.api;

import cn.hutool.json.JSONUtil;
import cn.hutool.log.Log;
import cn.hutool.log.LogFactory;
import com.fasterxml.jackson.annotation.JsonAnyGetter;
import com.xiashitech.apiservice.Constants.EnAndDecryption;
import com.xiashitech.apiservice.Constants.ErrorCode;
import com.xiashitech.apiservice.config.AuthConfig;
import com.xiashitech.apiservice.dto.AuthFactDTO;
import com.xiashitech.interfaces.agent.dto.SystemInfoDTO;
import com.xiashitech.interfaces.apiservice.dto.AuthFactRequest;
import com.xiashitech.interfaces.apiservice.dto.AuthFactResponse;
import com.xiashitech.interfaces.apiservice.dto.base.Response;
import com.xiashitech.apiservice.service.IAuthFactService;
import com.xiashitech.apiservice.service.IEnAndDecryption;
import com.xiashitech.apiservice.util.AuthFactSignParam;
import com.xiashitech.apiservice.util.BeanCopierUtil;
import com.xiashitech.apiservice.util.EnAndDecryptionHolder;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.util.Optional;

/**
 * 权限事实controller，根据用户访问的tracing数据生成权限事实
 */
@Controller
@RequestMapping(value = "/v1/agent")
@RequiredArgsConstructor(onConstructor =@_(@Autowired))
public class AuthFactController {
    private static final Log log = LogFactory.get();
    private final IAuthFactService authFactService;

    private final EnAndDecryptionHolder enAndDecryptionHolder;

    private final AuthConfig authConfig;

    @RequestMapping(value = "/supplementTracing", method = RequestMethod.POST)
    @ResponseBody
    public AuthFactResponse supplementUserTracing(@RequestBody AuthFactRequest authFactRequest) {
        if(authConfig.getIsSign()) {
            String signType = Optional.ofNullable(authConfig.getSignType()).orElse(EnAndDecryption.SIGNTYPE_MD5);
            IEnAndDecryption enAndDecryption = enAndDecryptionHolder.getEnAndDecryptionMap().get(signType);
            Boolean verifySign = enAndDecryption.verifySign(authFactRequest.getSign(), AuthFactSignParam.generateSignParam(authFactRequest) + authConfig.getSecurityKey());
            if(!verifySign) {
                return AuthFactResponse.builder().code(ErrorCode.RESULT_4002.getCode()).message(ErrorCode.RESULT_4002.getMessage()).build();
            }
        }
        log.info("authFactRequest: {}", JSONUtil.toJsonStr(authFactRequest));
        AuthFactDTO request = AuthFactDTO.builder().systemId(authFactRequest.getSystemId()).userId(authFactRequest.getUserId()).sign(authFactRequest.getSign()).appCode(authFactRequest.getAppCode())
                .instance(authFactRequest.getDb().getInstance()).database(authFactRequest.getDb().getDatabase()).schema(authFactRequest.getDb().getSchema())
                .sql(authFactRequest.getDb().getSql()).ip(authFactRequest.getDb().getIp()).port(authFactRequest.getDb().getPort()).type(authFactRequest.getDb().getType()).sourceSystemId(authFactRequest.getSourceSystemId()).apiName(authFactRequest.getApiName()).apiSystemId(authFactRequest.getApiSystemId()).build();
        AuthFactDTO authFactDTO = null;
        if(authConfig.isUseAllAuthInMemory())
            authFactDTO = authFactService.supplementUserTracingCache(request);
        else
            authFactDTO = authFactService.supplementUserTracing(request);
        AuthFactResponse authFactResponse = BeanCopierUtil.copy(authFactDTO, AuthFactResponse.class);
        log.info("authFactDTO: {}", JSONUtil.toJsonStr(authFactDTO));
        if(authFactResponse.getCode() == null) {
            authFactResponse.setCode(ErrorCode.RESULT_1001.getCode());
            authFactResponse.setMessage(ErrorCode.RESULT_1001.getMessage());
        } else {
            //TODO 日志太多，暂时注释掉 log.error("请求处理错误{}",authFactResponse.getMessage());
        }
        return authFactResponse;
    }

    /**
     * agent启动时从权限中心获取第三方系统信息
     * @param authFactRequest
     * @return
     */
    @RequestMapping(value = "/getSystemInfo", method = RequestMethod.POST)
    @ResponseBody
    public AuthFactResponse getSystemInfo(@RequestBody AuthFactRequest authFactRequest) {
        if(authConfig.getIsSign()) {
            String signType = Optional.ofNullable(authConfig.getSignType()).orElse(EnAndDecryption.SIGNTYPE_MD5);
            IEnAndDecryption enAndDecryption = enAndDecryptionHolder.getEnAndDecryptionMap().get(signType);
            Boolean verifySign = enAndDecryption.verifySign(authFactRequest.getSign(), AuthFactSignParam.generateSignParam(authFactRequest) + authConfig.getSecurityKey());
            if(!verifySign) {
                return AuthFactResponse.builder().code(ErrorCode.RESULT_4002.getCode()).message(ErrorCode.RESULT_4002.getMessage()).build();
            }
        }
        AuthFactDTO authFactDTO = authFactService.getSystemInfo(AuthFactDTO.builder().systemId(authFactRequest.getSystemId()).appCode(authFactRequest.getAppCode()).build());
        AuthFactResponse authFactResponse = AuthFactResponse.builder().systemInfoDTO(authFactDTO.getSystemInfoDTO()).code(authFactDTO.getCode()).message(authFactDTO.getMessage()).build();
        if(authFactResponse.getCode() == null) {
            authFactResponse.setCode(ErrorCode.RESULT_1001.getCode());
            authFactResponse.setMessage(ErrorCode.RESULT_1001.getMessage());
        } else {
            log.error("请求处理错误{}",authFactResponse.getMessage());
        }
        return authFactResponse;
    }
}
